home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / glass / glass.lha / GLASS / widgets / Command.c next >
Encoding:
C/C++ Source or Header  |  1991-02-01  |  16.4 KB  |  612 lines

  1. #ifndef lint
  2. static char Xrcsid[] = "$XConsortium: Command.c,v 1.70 89/12/12 20:17:23 swick Exp $";
  3. #endif /* lint */
  4.  
  5. /***********************************************************
  6. Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
  7. and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
  8.  
  9.                         All Rights Reserved
  10.  
  11. Permission to use, copy, modify, and distribute this software and its 
  12. documentation for any purpose and without fee is hereby granted, 
  13. provided that the above copyright notice appear in all copies and that
  14. both that copyright notice and this permission notice appear in 
  15. supporting documentation, and that the names of Digital or MIT not be
  16. used in advertising or publicity pertaining to distribution of the
  17. software without specific, written prior permission.  
  18.  
  19. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  20. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  21. DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  22. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  23. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  24. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  25. SOFTWARE.
  26.  
  27. ******************************************************************/
  28.  
  29.  
  30. /*
  31.  * Command.c - Command button widget
  32.  *
  33.  */
  34.  
  35. #include <stdio.h>
  36.  
  37. #include <X11/IntrinsicP.h>
  38. #include <X11/StringDefs.h>
  39. #include <X11/Xmu/Misc.h>
  40. #include <X11/Xaw/XawInit.h>
  41. #include "CommandP.h"
  42.  
  43. #ifdef SHAPE
  44. #include <X11/Xmu/Converters.h>
  45. #endif
  46.  
  47. #define DEFAULT_HIGHLIGHT_THICKNESS 2
  48.  
  49. #ifdef SHAPE
  50. #    define DEFAULT_SHAPE_HIGHLIGHT 32767
  51. #endif
  52.  
  53. /****************************************************************
  54.  *
  55.  * Full class record constant
  56.  *
  57.  ****************************************************************/
  58.  
  59. /* Private Data */
  60.  
  61. static char defaultTranslations[] =
  62.     "<EnterWindow>:    highlight()        \n\
  63.      <LeaveWindow>:    reset()            \n\
  64.      <Btn1Down>:    set()            \n\
  65.      <Btn1Up>:        notify() unset()    ";
  66.  
  67. #define offset(field) XtOffset(CommandWidget, field)
  68. static XtResource resources[] = { 
  69.  
  70.    {XtNcallback, XtCCallback, XtRCallback, sizeof(XtPointer), 
  71.       offset(command.callbacks), XtRCallback, (XtPointer)NULL},
  72.    {XtNhighlightThickness, XtCThickness, XtRDimension, sizeof(Dimension),
  73. #ifndef SHAPE
  74.       offset(command.highlight_thickness), XtRImmediate,
  75.       (XtPointer)DEFAULT_HIGHLIGHT_THICKNESS },
  76. #else
  77.       offset(command.highlight_thickness), XtRImmediate,
  78.       (XtPointer) DEFAULT_SHAPE_HIGHLIGHT},
  79.  
  80.    {XtNshapeStyle, XtCShapeStyle, XtRShapeStyle, sizeof(int),
  81.       offset(command.shape_style), XtRImmediate, (XtPointer)XawShapeRectangle},
  82.    {XtNcornerRoundPercent, XtCCornerRoundPercent, 
  83.     XtRDimension, sizeof(Dimension),
  84.     offset(command.corner_round), XtRImmediate, (XtPointer) 25},
  85. #endif /*SHAPE*/
  86. };
  87. #undef offset
  88.  
  89. static Boolean SetValues();
  90. static void Initialize(), Redisplay(), Set(), Reset(), Notify(), Unset();
  91. static void Highlight(), Unhighlight(), Destroy(), PaintCommandWidget();
  92. static void ClassInitialize();
  93.  
  94. #ifdef SHAPE
  95. static Boolean ShapeButton();
  96. static void Realize(), Resize();
  97. #endif /* SHAPE */
  98.  
  99. static XtActionsRec actionsList[] =
  100. {
  101.   {"set",        Set},
  102.   {"notify",        Notify},
  103.   {"highlight",        Highlight},
  104.   {"reset",        Reset},
  105.   {"unset",        Unset},
  106.   {"unhighlight",    Unhighlight},
  107. };
  108.  
  109. /*
  110.  * This is a temporary exported actions list for the command
  111.  * widget I have added this code because there is a bug in the MIT
  112.  * Xtk Intrinsics implementation that does not allow the action table
  113.  * to be retreived from the widget class, Ralph Swick has promised me that
  114.  * this will eventually be fixed, but until then this is how the toggle
  115.  * widget will get the command widget's actions list.
  116.  *
  117.  * Chris D. Peterson - 12/28/88.
  118.  */
  119.  
  120. XtActionList xaw_command_actions_list = actionsList;
  121.  
  122. #define SuperClass ((LabelWidgetClass)&labelClassRec)
  123.  
  124. CommandClassRec commandClassRec = {
  125.   {
  126.     (WidgetClass) SuperClass,        /* superclass          */    
  127.     "Command",                /* class_name          */
  128.     sizeof(CommandRec),            /* size              */
  129.     ClassInitialize,            /* class_initialize      */
  130.     NULL,                /* class_part_initialize  */
  131.     FALSE,                /* class_inited          */
  132.     Initialize,                /* initialize          */
  133.     NULL,                /* initialize_hook      */
  134. #ifdef SHAPE
  135.     Realize,                /* realize          */
  136. #else
  137.     XtInheritRealize,            /* realize          */
  138. #endif /*SHAPE*/
  139.     actionsList,            /* actions          */
  140.     XtNumber(actionsList),        /* num_actions          */
  141.     resources,                /* resources          */
  142.     XtNumber(resources),        /* resource_count      */
  143.     NULLQUARK,                /* xrm_class          */
  144.     FALSE,                /* compress_motion      */
  145.     TRUE,                /* compress_exposure      */
  146.     TRUE,                /* compress_enterleave    */
  147.     FALSE,                /* visible_interest      */
  148.     Destroy,                /* destroy          */
  149. #ifdef SHAPE
  150.     Resize,                /* resize          */
  151. #else
  152.     XtInheritResize,            /* resize          */
  153. #endif /* SHAPE */
  154.     Redisplay,                /* expose          */
  155.     SetValues,                /* set_values          */
  156.     NULL,                /* set_values_hook      */
  157.     XtInheritSetValuesAlmost,        /* set_values_almost      */
  158.     NULL,                /* get_values_hook      */
  159.     NULL,                /* accept_focus          */
  160.     XtVersion,                /* version          */
  161.     NULL,                /* callback_private      */
  162.     defaultTranslations,        /* tm_table          */
  163.     XtInheritQueryGeometry,        /* query_geometry      */
  164.     XtInheritDisplayAccelerator,    /* display_accelerator      */
  165.     NULL                /* extension          */
  166.   },  /* CoreClass fields initialization */
  167.   {
  168.     XtInheritChangeSensitive        /* change_sensitive    */
  169.   },  /* SimpleClass fields initialization */
  170.   {
  171.     0,                                     /* field not used    */
  172.   },  /* LabelClass fields initialization */
  173.   {
  174.     0,                                     /* field not used    */
  175.   },  /* CommandClass fields initialization */
  176. };
  177.  
  178.   /* for public consumption */
  179. WidgetClass commandWidgetClass = (WidgetClass) &commandClassRec;
  180.  
  181. /****************************************************************
  182.  *
  183.  * Private Procedures
  184.  *
  185.  ****************************************************************/
  186.  
  187. static GC 
  188. Get_GC(cbw, fg, bg)
  189. CommandWidget cbw;
  190. Pixel fg, bg;
  191. {
  192.   XGCValues    values;
  193.   
  194.   values.foreground   = fg;
  195.   values.background    = bg;
  196.   values.font        = cbw->label.font->fid;
  197.   values.cap_style = CapProjecting;
  198.   
  199.   if (cbw->command.highlight_thickness > 1 )
  200.     values.line_width   = cbw->command.highlight_thickness;
  201.   else 
  202.     values.line_width   = 0;
  203.   
  204.   return XtGetGC((Widget)cbw,
  205.          (GCForeground|GCBackground|GCFont|GCLineWidth|GCCapStyle),
  206.          &values);
  207. }
  208.  
  209.  
  210. /* ARGSUSED */
  211. static void 
  212. Initialize(request, new, args, num_args)
  213. Widget request, new;
  214. ArgList args;            /* unused */
  215. Cardinal *num_args;        /* unused */
  216. {
  217.   CommandWidget cbw = (CommandWidget) new;
  218. #ifdef SHAPE
  219.   int shape_event_base, shape_error_base;
  220.  
  221.   if (cbw->command.shape_style != XawShapeRectangle
  222.       && !XShapeQueryExtension(XtDisplay(new), &shape_event_base, 
  223.                    &shape_error_base))
  224.       cbw->command.shape_style = XawShapeRectangle;
  225.   if (cbw->command.highlight_thickness == DEFAULT_SHAPE_HIGHLIGHT) {
  226.       if (cbw->command.shape_style != XawShapeRectangle)
  227.       cbw->command.highlight_thickness = 0;
  228.       else
  229.       cbw->command.highlight_thickness = DEFAULT_HIGHLIGHT_THICKNESS;
  230.   }
  231. #endif /*SHAPE*/
  232.  
  233.   cbw->command.normal_GC = Get_GC(cbw, cbw->label.foreground, 
  234.                   cbw->core.background_pixel);
  235.   cbw->command.inverse_GC = Get_GC(cbw, cbw->core.background_pixel, 
  236.                    cbw->label.foreground);
  237.   XtReleaseGC(new, cbw->label.normal_GC);
  238.   cbw->label.normal_GC = cbw->command.normal_GC;
  239.  
  240.   cbw->command.set = FALSE;
  241.   cbw->command.highlighted = HighlightNone;
  242. }
  243.  
  244. static Region 
  245. HighlightRegion(cbw)
  246. CommandWidget cbw;
  247. {
  248.   static Region outerRegion = NULL, innerRegion, emptyRegion;
  249.   XRectangle rect;
  250.  
  251.   if (cbw->command.highlight_thickness == 0 ||
  252.       cbw->command.highlight_thickness > Min(cbw->core.width,
  253.                          cbw->core.height)/2)
  254.     return(NULL);
  255.  
  256.   if (outerRegion == NULL) {
  257.     /* save time by allocating scratch regions only once. */
  258.     outerRegion = XCreateRegion();
  259.     innerRegion = XCreateRegion();
  260.     emptyRegion = XCreateRegion();
  261.   }
  262.  
  263.   rect.x = rect.y = 0;
  264.   rect.width = cbw->core.width;
  265.   rect.height = cbw->core.height;
  266.   XUnionRectWithRegion( &rect, emptyRegion, outerRegion );
  267.   rect.x = rect.y = cbw->command.highlight_thickness;
  268.   rect.width -= cbw->command.highlight_thickness * 2;
  269.   rect.height -= cbw->command.highlight_thickness * 2;
  270.   XUnionRectWithRegion( &rect, emptyRegion, innerRegion );
  271.   XSubtractRegion( outerRegion, innerRegion, outerRegion );
  272.   return outerRegion;
  273. }
  274.  
  275. /***************************
  276. *
  277. *  Action Procedures
  278. *
  279. ***************************/
  280.  
  281. /* ARGSUSED */
  282. static void 
  283. Set(w,event,params,num_params)
  284. Widget w;
  285. XEvent *event;
  286. String *params;        /* unused */
  287. Cardinal *num_params;    /* unused */
  288. {
  289.   CommandWidget cbw = (CommandWidget)w;
  290.  
  291.   if (cbw->command.set)
  292.     return;
  293.  
  294.   cbw->command.set= TRUE;
  295.   if (XtIsRealized(w))
  296.     PaintCommandWidget(w, (Region) NULL, TRUE);
  297. }
  298.  
  299. /* ARGSUSED */
  300. static void
  301. Unset(w,event,params,num_params)
  302. Widget w;
  303. XEvent *event;
  304. String *params;        /* unused */
  305. Cardinal *num_params;
  306. {
  307.   CommandWidget cbw = (CommandWidget)w;
  308.  
  309.   if (!cbw->command.set)
  310.     return;
  311.  
  312.   cbw->command.set = FALSE;
  313.   if (XtIsRealized(w)) {
  314.     XClearWindow(XtDisplay(w), XtWindow(w));
  315.     PaintCommandWidget(w, (Region) NULL, TRUE);
  316.   }
  317. }
  318.  
  319. /* ARGSUSED */
  320. static void 
  321. Reset(w,event,params,num_params)
  322. Widget w;
  323. XEvent *event;
  324. String *params;        /* unused */
  325. Cardinal *num_params;   /* unused */
  326. {
  327.   CommandWidget cbw = (CommandWidget)w;
  328.  
  329.   if (cbw->command.set) {
  330.     cbw->command.highlighted = HighlightNone;
  331.     Unset(w, event, params, num_params);
  332.   }
  333.   else
  334.     Unhighlight(w, event, params, num_params);
  335. }
  336.  
  337. /* ARGSUSED */
  338. static void 
  339. Highlight(w,event,params,num_params)
  340. Widget w;
  341. XEvent *event;
  342. String *params;        
  343. Cardinal *num_params;    
  344. {
  345.   CommandWidget cbw = (CommandWidget)w;
  346.  
  347.   if ( *num_params == (Cardinal) 0) 
  348.     cbw->command.highlighted = HighlightWhenUnset;
  349.   else {
  350.     if ( *num_params != (Cardinal) 1) 
  351.       XtWarning("Too many parameters passed to highlight action table.");
  352.     switch (params[0][0]) {
  353.     case 'A':
  354.     case 'a':
  355.       cbw->command.highlighted = HighlightAlways;
  356.       break;
  357.     default:
  358.       cbw->command.highlighted = HighlightWhenUnset;
  359.       break;
  360.     }
  361.   }
  362.  
  363.   if (XtIsRealized(w))
  364.     PaintCommandWidget(w, HighlightRegion(cbw), TRUE);
  365. }
  366.  
  367. /* ARGSUSED */
  368. static void 
  369. Unhighlight(w,event,params,num_params)
  370. Widget w;
  371. XEvent *event;
  372. String *params;        /* unused */
  373. Cardinal *num_params;    /* unused */
  374. {
  375.   CommandWidget cbw = (CommandWidget)w;
  376.  
  377.   cbw->command.highlighted = HighlightNone;
  378.   if (XtIsRealized(w))
  379.     PaintCommandWidget(w, HighlightRegion(cbw), TRUE);
  380. }
  381.  
  382. /* ARGSUSED */
  383. static void 
  384. Notify(w,event,params,num_params)
  385. Widget w;
  386. XEvent *event;
  387. String *params;        /* unused */
  388. Cardinal *num_params;    /* unused */
  389. {
  390.   CommandWidget cbw = (CommandWidget)w; 
  391.  
  392.   /* check to be sure state is still Set so that user can cancel
  393.      the action (e.g. by moving outside the window, in the default
  394.      bindings.
  395.   */
  396.   if (cbw->command.set)
  397.     XtCallCallbackList(w, cbw->command.callbacks, NULL);
  398. }
  399.  
  400. /*
  401.  * Repaint the widget window
  402.  */
  403.  
  404. /************************
  405. *
  406. *  REDISPLAY (DRAW)
  407. *
  408. ************************/
  409.  
  410. /* ARGSUSED */
  411. static void 
  412. Redisplay(w, event, region)
  413. Widget w;
  414. XEvent *event;
  415. Region region;
  416. {
  417.   PaintCommandWidget(w, region, FALSE);
  418. }
  419.  
  420. /*    Function Name: PaintCommandWidget
  421.  *    Description: Paints the command widget.
  422.  *    Arguments: w - the command widget.
  423.  *                 region - region to paint (passed to the superclass).
  424.  *                 change - did it change either set or highlight state?
  425.  *    Returns: none
  426.  */
  427.  
  428. static void 
  429. PaintCommandWidget(w, region, change)
  430. Widget w;
  431. Region region;
  432. Boolean change;
  433. {
  434.   CommandWidget cbw = (CommandWidget) w;
  435.   Boolean very_thick;
  436.   GC norm_gc, rev_gc;
  437.    
  438.   very_thick = cbw->command.highlight_thickness > Min(cbw->core.width,
  439.                               cbw->core.height)/2;
  440.  
  441.   if (cbw->command.set) {
  442.     cbw->label.normal_GC = cbw->command.inverse_GC;
  443.     XFillRectangle(XtDisplay(w), XtWindow(w), cbw->command.normal_GC,
  444.            0, 0, cbw->core.width, cbw->core.height);
  445.     region = NULL;        /* Force label to repaint text. */
  446.   }
  447.   else
  448.       cbw->label.normal_GC = cbw->command.normal_GC;
  449.  
  450.   if (cbw->command.highlight_thickness <= 0)
  451.   {
  452.     (*SuperClass->core_class.expose) (w, (XEvent *) NULL, region);
  453.     return;
  454.   }
  455.  
  456. /*
  457.  * If we are set then use the same colors as if we are not highlighted. 
  458.  */
  459.  
  460.   if (cbw->command.set == (cbw->command.highlighted == HighlightNone)) {
  461.     norm_gc = cbw->command.inverse_GC;
  462.     rev_gc = cbw->command.normal_GC;
  463.   }
  464.   else {
  465.     norm_gc = cbw->command.normal_GC;
  466.     rev_gc = cbw->command.inverse_GC;
  467.   }
  468.  
  469.   if ( !( (!change && (cbw->command.highlighted == HighlightNone)) ||
  470.       ((cbw->command.highlighted == HighlightWhenUnset) &&
  471.        (cbw->command.set))) ) {
  472.     if (very_thick) {
  473.       cbw->label.normal_GC = norm_gc; /* Give the label the right GC. */
  474.       XFillRectangle(XtDisplay(w),XtWindow(w), rev_gc,
  475.              0, 0, cbw->core.width, cbw->core.height);
  476.     }
  477.     else {
  478.       /* wide lines are centered on the path, so indent it */
  479.       int offset = cbw->command.highlight_thickness/2;
  480.       XDrawRectangle(XtDisplay(w),XtWindow(w), rev_gc, offset, offset, 
  481.              cbw->core.width - cbw->command.highlight_thickness,
  482.              cbw->core.height - cbw->command.highlight_thickness);
  483.     }
  484.   }
  485.   (*SuperClass->core_class.expose) (w, (XEvent *) NULL, region);
  486. }
  487.  
  488. static void 
  489. Destroy(w)
  490. Widget w;
  491. {
  492.   CommandWidget cbw = (CommandWidget) w;
  493.  
  494.   /* so Label can release it */
  495.   if (cbw->label.normal_GC == cbw->command.normal_GC)
  496.     XtReleaseGC( w, cbw->command.inverse_GC );
  497.   else
  498.     XtReleaseGC( w, cbw->command.normal_GC );
  499. }
  500.  
  501. /*
  502.  * Set specified arguments into widget
  503.  */
  504.  
  505. /* ARGSUSED */
  506. static Boolean 
  507. SetValues (current, request, new)
  508. Widget current, request, new;
  509. {
  510.   CommandWidget oldcbw = (CommandWidget) current;
  511.   CommandWidget cbw = (CommandWidget) new;
  512.   Boolean redisplay = False;
  513.  
  514.   if ( oldcbw->core.sensitive != cbw->core.sensitive && !cbw->core.sensitive) {
  515.     /* about to become insensitive */
  516.     cbw->command.set = FALSE;
  517.     cbw->command.highlighted = HighlightNone;
  518.     redisplay = TRUE;
  519.   }
  520.   
  521.   if ( (oldcbw->label.foreground != cbw->label.foreground)           ||
  522.        (oldcbw->core.background_pixel != cbw->core.background_pixel) ||
  523.        (oldcbw->command.highlight_thickness != 
  524.                                    cbw->command.highlight_thickness) ||
  525.        (oldcbw->label.font != cbw->label.font) ) 
  526.   {
  527.     if (oldcbw->label.normal_GC == oldcbw->command.normal_GC)
  528.     /* Label has release one of these */
  529.       XtReleaseGC(new, cbw->command.inverse_GC);
  530.     else
  531.       XtReleaseGC(new, cbw->command.normal_GC);
  532.  
  533.     cbw->command.normal_GC = Get_GC(cbw, cbw->label.foreground, 
  534.                     cbw->core.background_pixel);
  535.     cbw->command.inverse_GC = Get_GC(cbw, cbw->core.background_pixel, 
  536.                      cbw->label.foreground);
  537.     XtReleaseGC(new, cbw->label.normal_GC);
  538.     cbw->label.normal_GC = (cbw->command.set
  539.                 ? cbw->command.inverse_GC
  540.                 : cbw->command.normal_GC);
  541.     
  542.     redisplay = True;
  543.   }
  544.  
  545. #ifdef SHAPE
  546.   if ( XtIsRealized(new)
  547.        && oldcbw->command.shape_style != cbw->command.shape_style
  548.        && !ShapeButton(cbw))
  549.   {
  550.       cbw->command.shape_style = oldcbw->command.shape_style;
  551.   }
  552. #endif /*SHAPE*/
  553.  
  554.   return (redisplay);
  555. }
  556.  
  557. static void ClassInitialize()
  558. {
  559.     XawInitializeWidgetSet();
  560. #ifdef SHAPE
  561.     XtSetTypeConverter( XtRString, XtRShapeStyle, XmuCvtStringToShapeStyle,
  562.                 NULL, 0, XtCacheNone, NULL );
  563. #endif
  564. }
  565.  
  566.  
  567.  
  568. #ifdef SHAPE
  569.  
  570. static Boolean
  571. ShapeButton(cbw)
  572. CommandWidget cbw;
  573. {
  574.     Dimension corner_size;
  575.  
  576.     if ( (cbw->command.shape_style == XawShapeRoundedRectangle) ) {
  577.     corner_size = (cbw->core.width < cbw->core.height) ? cbw->core.width 
  578.                                                        : cbw->core.height;
  579.     corner_size = (corner_size * cbw->command.corner_round) / 100;
  580.     }
  581.  
  582.     if (cbw->command.shape_style != XawShapeRectangle) {
  583.     if (!XmuReshapeWidget((Widget) cbw, cbw->command.shape_style,
  584.                   corner_size, corner_size)) {
  585.         cbw->command.shape_style = XawShapeRectangle;
  586.         return(False);
  587.     }
  588.     }
  589.     return(TRUE);
  590. }
  591.  
  592. static void Realize(w, valueMask, attributes)
  593.     Widget w;
  594.     Mask *valueMask;
  595.     XSetWindowAttributes *attributes;
  596. {
  597.     (*commandWidgetClass->core_class.superclass->core_class.realize)
  598.     (w, valueMask, attributes);
  599.  
  600.     ShapeButton( (CommandWidget) w);
  601. }
  602.  
  603. static void Resize(w)
  604.     Widget w;
  605. {
  606.     if (XtIsRealized(w)) 
  607.     ShapeButton( (CommandWidget) w);
  608.  
  609.     (*commandWidgetClass->core_class.superclass->core_class.resize)(w);
  610. }
  611. #endif /*SHAPE*/
  612.